﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CommunicationLib.Model
{
    /// <summary>
    /// 环形缓冲区管理器
    /// </summary>
    public partial class RingBufferManager
    {
        /// <summary>
        /// 存放字节数组
        /// </summary>
        public byte[] Buffer { get;  set; }
        /// <summary>
        /// 写入数据长度
        /// </summary>
        public int DataCount { get;  set; }
        /// <summary>
        /// 数据起始索引
        /// </summary>
        public int DataStart { get; set; }= 0;
        /// <summary>
        /// 数据结束索引
        /// </summary>
        public int DataEnd { get; set; }= 0;
        public DateTime ReceiveTime { get; internal set; }

        public RingBufferManager(int size)
        {
            Buffer = new byte[size];
            DataCount = 0;
            DataStart = 0;
            DataEnd = 0;
        }
        public void WriteBuffer(byte[] buffer)
        {
            WriteBuffer(buffer, 0, buffer.Length);
        }
        /// <summary>
        ///   写入数据到缓冲区
        /// </summary>
        /// <param name="buffer"></param>
        /// <param name="offset"></param>
        /// <param name="count"></param>
        /// <exception cref="InvalidOperationException"></exception>

        public void WriteBuffer(byte[] buffer,int offset,int count)
        {
           int reserveCount = Buffer.Length - DataCount;
            if (count > reserveCount)
            {
                throw new InvalidOperationException("缓冲区已满，无法写入更多数据");
            }
            else if (DataEnd + count < Buffer.Length)
            {
                //数据没到结尾
               Array.Copy(buffer, offset, Buffer, DataEnd, count);
                DataEnd += count;
                DataCount += count;
            }
            else
            {
                //数据到结尾了
                int overflowIndexLength = (DataEnd + count) - Buffer.Length;// 计算超过索引的长度
                int endPushIndexLength = count - overflowIndexLength; // 填充在末尾的数据长度
                Array.Copy(buffer, offset, Buffer, DataEnd, endPushIndexLength);// 填充到末尾
                DataEnd = 0; // 重置结束索引
                offset += endPushIndexLength; // 更新偏移量
                DataCount += endPushIndexLength; // 更新数据长度
               if(overflowIndexLength!=0)// 如果有溢出数据
                {
                   Array.Copy(buffer, offset, Buffer, DataEnd, overflowIndexLength);// 填充溢出数据
                  
                }
                DataEnd += overflowIndexLength;
                DataCount += overflowIndexLength; // 更新数据长度
            }
          
        }
        /// <summary>
        /// 从缓冲区读取数据
        /// </summary>
        /// <param name="targetBytes"></param>
        /// <param name="offset"></param>
        /// <param name="count"></param>
        /// <exception cref="InvalidOperationException"></exception>
        public void ReadBuffer(byte[] targetBytes, int offset, int count)
        {
           if (count > DataCount)
            {
                throw new InvalidOperationException("缓冲区没有足够的数据可供读取");
            }
           if(DataStart + count < Buffer.Length)
            {
                Array.Copy(Buffer, DataStart, targetBytes, offset, count);
            }
            else
            {
                // 数据到结尾了
                int overflowIndexLength = Buffer.Length - DataStart; // 计算到结尾的长度
                int endReadIndexLength = count - overflowIndexLength; // 计算需要读取的剩余长度
                Array.Copy(Buffer, DataStart, targetBytes, offset, endReadIndexLength); // 先读取到结尾
                offset += endReadIndexLength; // 更新偏移量
                if (overflowIndexLength != 0) // 如果还有剩余数据
                {
                    Array.Copy(Buffer, 0, targetBytes, offset, overflowIndexLength); // 继续读取剩余数据
                    DataStart += overflowIndexLength; // 更新起始索引
                }
            }
        }
        public void Clear(int count)
        {
            if(count> DataCount)
            {
                DataStart = 0;
                DataEnd = 0;
                DataCount = 0;
            }
            else
            {
               if(DataStart + count >= Buffer.Length)// 如果起始索引加上清除长度超过缓冲区长度
                {
                    DataStart = (DataStart + count) - Buffer.Length; // 重置起始索引
                }
                else
                {
                    DataCount += count;// 更新数据长度
                }
                DataCount -= count;// 更新数据长度
            }
        }

        public void Clear()
        {
            DataStart = 0;
            DataEnd = 0;
            DataCount = 0;
        }
        /// <summary>
        /// 获取当前缓冲区的数据长度
        /// </summary>
        /// <returns></returns>
        public int GetDataCount()=> DataCount;
        /// <summary>
        /// 获取当前缓冲区的剩余可用长度
        /// </summary>
        /// <returns></returns>
        public int GetReserverCount()=> Buffer.Length - DataCount;

        public byte this[int index]
        {
            get
            {
                if (index < 0 || index >= DataCount)
                {
                    throw new IndexOutOfRangeException("索引超出范围");
                }
                if (DataStart + index < Buffer.Length)// 如果索引在当前缓冲区范围内
                {
                    return Buffer[DataStart + index]; // 直接返回数据
                }
                else
                {
                    int actualIndex = (DataStart + index) - Buffer.Length; // 计算实际索引
                    return Buffer[actualIndex]; // 返回环形缓冲区中的数据
                }
            }
        }
    }
}
